// ExecStub.cpp: implementation of the CExecStub class.
//
//////////////////////////////////////////////////////////////////////

#include "ExecStub.h"
#include <assert.h>
#include <process.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CExecStub::CExecStub()
{
    m_hExecWnd = NULL;
}

CExecStub::~CExecStub()
{
}
///////////////////////////////////////////////////////////////////////

#define GET_ACK(x) \
    do { \
        x.message = 0; \
        BOOL bRet = GetMessage(&x, NULL, MSG_EX_ACK, MSG_EX_ACK); \
        if (!bRet) { \
            _endthread(); \
        } \
    } while (0)

void CExecStub::SetExecWnd (HWND hwnd)
{
    m_hExecWnd = hwnd;
}

void CExecStub::canvassize (double x, double y)
{
    MSG msg;
    DblPoint size;
    assert (m_hExecWnd);

    size.x = x;
    size.y = y;
    ::PostMessage(m_hExecWnd, MSG_EX_CS, (WPARAM)&size, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::reset (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_RESET, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::clear (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_CLEAR, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::hide (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_HIDE, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::canvascolor (double r, double g, double b)
{
    MSG msg;
    DblRGB clr;
    assert (m_hExecWnd);

    clr.r = r;
    clr.g = g;
    clr.b = b;
    ::PostMessage(m_hExecWnd, MSG_EX_CC, (WPARAM)&clr, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::pencolor (double r, double g, double b)
{
    MSG msg;
    DblRGB clr;
    assert (m_hExecWnd);

    clr.r = r;
    clr.g = g;
    clr.b = b;
    ::PostMessage(m_hExecWnd, MSG_EX_PC, (WPARAM)&clr, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::penwidth (double w)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_PW, (WPARAM)&w, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::go (double x, double y)
{
    MSG msg;
    DblPoint pt;
    assert (m_hExecWnd);

    pt.x = x;
    pt.y = y;
    ::PostMessage(m_hExecWnd, MSG_EX_GO, (WPARAM)&pt, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::direction (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_DIR, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::turnright (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_TR, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::turnleft (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_TL, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::forward (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_FW, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::backward (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_BW, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::fontsize (double n)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_FONTSIZE, (WPARAM)&n, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::print (char* str)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_PRINT, (WPARAM)str, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::penup (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_PU, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::pendown (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_PD, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::center (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_CENTER, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::gox (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_GOX, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::goy (double d)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_GOY, (WPARAM)&d, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::wrapon (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_WRAPON, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::wrapoff (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_WRAPOFF, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::show (void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_SHOW, NULL, GetCurrentThreadId());
    GET_ACK(msg);
}

/* the returned string shall NOT be freed by the caller. */
char* CExecStub::inputwindow (char* str)
{
    MSG msg;
    static char szInput[INPUT_SIZE];
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_INPUT, (WPARAM)str, GetCurrentThreadId());
    GET_ACK(msg);
    strncpy (szInput, (char*)msg.wParam, INPUT_SIZE);
    return (szInput);
}

void CExecStub::message (char* str)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_MSG, (WPARAM)str, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::debug_info (char* str)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_DBGINFO, (WPARAM)str, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::error_info (char* str)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_ERRINFO, (WPARAM)str, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::done(void)
{
    MSG msg;
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_EX_DONE, (WPARAM)0, GetCurrentThreadId());
    GET_ACK(msg);
}

void CExecStub::debug_cmd_ack(int lineno)
{
    assert (m_hExecWnd);

    ::PostMessage(m_hExecWnd, MSG_DEBUG_ACK, (WPARAM)lineno, GetCurrentThreadId());
}


